package org.ym.database.hibernate.base;

import com.google.gson.JsonObject;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.query.QueryUtils;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.ym.database.hibernate.query.QueryFilter;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ym
 */
@NoRepositoryBean
public class BaseRepositoryImpl<T extends BaseModel,ID> extends SimpleJpaRepository<T, ID> implements BaseRepository<T,ID> {

    protected EntityManager entityManager;

    public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
    }

    public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager = entityManager;
    }

    /**
     * 查询所有数据
     * @param queryFilter 查询条件
     * @param classZ 当前类
     * @return 数据
     */
    @Override
    public List<T> queryAll(QueryFilter queryFilter, Class<T> classZ){
        if(queryFilter == null){
            return new ArrayList<>();
        }
        if(queryFilter.getSort() != null){
            return findAll(queryFilter.toSpecification(classZ),queryFilter.getSort());
        }else{
            return findAll(queryFilter.toSpecification(classZ));
        }
    }

    /**
     * 分页查询数据
     * @param queryFilter 查询条件
     * @param classZ 当前类
     * @return 数据
     */
    @Override
    public Page<T> queryPage(QueryFilter queryFilter, Class<T> classZ){
        if(queryFilter == null){
            return null;
        }
        if(!queryFilter.isPaging()){
            queryFilter.setCurrentPageIndex(QueryFilter.DEFAULT_CURRENT_PAGE_INDEX);
        }
        return findAll(queryFilter.toSpecification(classZ),queryFilter.getPageable());
    }

    /**
     * 根据条件查询数量
     * @param queryFilter 查询条件
     * @param classZ 类
     * @return 数量
     */
    @Override
    public long count(QueryFilter queryFilter, Class<T> classZ) {
        if(queryFilter == null){
            return 0;
        }
        return count(queryFilter.toSpecification(classZ));
    }

    /**
     * 查询所有数据,支持min、max、分组查询等
     * @param queryFilter 查询条件
     * @param classZ 表类
     * @return 数据
     */
    @Override
    public List<Object> query(QueryFilter queryFilter, Class<T> classZ){
        if(queryFilter == null){
            return new ArrayList<>();
        }
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery(Object.class);
        Root<T> root = criteriaQuery.from(classZ);
        Specification<T> specification = queryFilter.toSpecification(classZ);
        Predicate predicate = specification.toPredicate(root,criteriaQuery,criteriaBuilder);
        if(predicate != null){
            criteriaQuery.where(predicate);
        }
        if(queryFilter.getSort() != null){
            criteriaQuery.orderBy(QueryUtils.toOrders(queryFilter.getSort(),root,criteriaBuilder));
        }
        return entityManager.createQuery(criteriaQuery).getResultList();
    }

    /**
     * 查询所有数据，并把查询结果转换成JsonObject
     * @param queryFilter 查询条件
     * @param classZ 表类
     * @return 数据集
     */
    @Override
    public List<JsonObject> queryAsJsonObject(QueryFilter queryFilter, Class<T> classZ) {
        List<Object> objectList = query(queryFilter,classZ);
        return queryFilter.changeToJsonObject(objectList);
    }
}
